package com.yingyi.basic.intercepter;

import com.yingyi.basic.annotation.PreAuthorize;
import com.yingyi.basic.constant.Identity;
import com.yingyi.basic.jwt.JwtUtils;
import com.yingyi.basic.jwt.Payload;
import com.yingyi.basic.jwt.RsaUtils;
import com.yingyi.org.mapper.EmployeeMapper;
import com.yingyi.user.domain.Logininfo;
import com.yingyi.user.util.LoginData;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.PublicKey;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component //将当前的类交给Spring管理
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private EmployeeMapper employeeMapper;
    /**
     *
     * 需要配合拦截器的配置类（相当于以前的xml形式配置拦截器）使用
     *
     * 后台的登录拦截
     * 思路：
     *  1 从请求头中获取token
     *  2 用token作为键查询redis中是否有对应的logininfo值
     *    有则表示已经登录过，【刷新登录信息的过期时间】，放行请求
     *    无则表示未登录或者登录已经过期，向前端响应未登录的信息 使用JsonResult对应的格式，需要进行Json格式字符串的拼接
     *
     * 【New 使用JwtToken验证】
     *  登录验证
     *      1 获取token（JwtToken）
     *      2 如果能获取到token则登录过，进行权限验证，没有直接返回false提示需要登录的信息
     *      3 获取公钥，对token解密 过期判断，获取LoginData（logininfo、permissions）
     *      4 对后台管理员进行权限验证
     *          获取当前接口上注解里面的sn，查询当前登陆人的所有权限，进行判断
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取token(JwtToken)
        String token = request.getHeader("token");

        if(token != null && !token.isEmpty()){
            //logininfo = redisTemplate.opsForValue().get(token);
            try {
                // 解析token里面内容
                PublicKey publicKey = RsaUtils.getPublicKey(JwtUtils.class.getClassLoader().getResource("auth_rsa.pub").getFile());
                Payload<LoginData> payload = JwtUtils.getInfoFromToken(token, publicKey, LoginData.class);

                if(payload != null){//登录信息没有过期
                    LoginData loginData = payload.getLoginData();
                    Logininfo logininfo = loginData.getLogininfo();

                    if (logininfo.getType().equals(Identity.USER)) {
                        //如果是普通用户user则直接放行
                        return true;
                    }

                    //验证后台管理人员的权限
                    //获取当前接口上注解中的sn
                    HandlerMethod handlerMethod = (HandlerMethod) handler;//接收请求的接口-方法
                    //获取注解@PreAuthorize
                    PreAuthorize annotation = handlerMethod.getMethodAnnotation(PreAuthorize.class);
                    if (annotation == null) {
                        //当前接口上没有这个注解-非受限资源直接放行
                        return true;
                    }

                    //接口上定义的权限
                    String sn = annotation.sn();
                    //从数据库中查询当前登录用户的权限
                    List<String> permissions = employeeMapper.getPermissionsByLogininfoId(logininfo.getId());

                    if (permissions.contains(sn)) {
                        //登陆人有权限-放行
                        return true;
                    } else {//else会经过后置拦截器，可以在axios后置拦截器中判断弹出错误框
                        response.setContentType("application/json;charset=UTF-8");
                        response.getWriter().println("{\"success\":false,\"message\":\"noPermission\"}");
                        return false;
                    }

                }
            } catch (ExpiredJwtException e) {
                e.printStackTrace();

                //当登录信息过期时，产生异常ExpiredJwtException
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().println("{\"success\":false,\"message\":\"timeout\"}");
                return false;
            } catch (Exception e) {
                e.printStackTrace();
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().println("{\"success\":false,\"message\":\"error\"}");
                return false;
            }

        }
        /*if(logininfo != null){
            //登陆过  刷新过期时间[重新添加到redis] + 放行
            redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
            return true;
        }*/

        System.out.println("=====================intercepter==================" + request.getRequestURL());
        //跳转到登录页面 - 后端跳不了，因为后端项目没有页面 - 放在前端跳转
        //告诉浏览器我要给你响应一个json数据，编码集为utf-8
        // {"success": false, "message": "noLogin"}
        response.setContentType("application/json;charset=UTF-8");

        //响应的结果在前端配合axios的后置处理器使用
        response.getWriter().write("{\"success\": false, \"message\": \"noLogin\"}");
        return false;
    }
}
